//#include	"unp.h"

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>
#include <netdb.h>
#include <sys/socket.h>
#include <signal.h>
#include <arpa/inet.h>

#include "win_types.h"
#include "keycode.h"

#define SERVER_PORT 	1026
#define MAX_NET_CLIENT 	5
#define RECV_BUF_SIZE 	1024
#define INVALID_SOCKET 	(-1) 
#define NULL 			((void *)0)

#define msleep(ms) usleep(ms*1000)

//typedef unsigned char * LPBYTE;
//typedef unsigned char BYTE;


//客户端连接信息
typedef struct
{
	int          	sck;
	struct sockaddr_in  addr;		//客户端Socket连接地址
	int 		    eCnnState;		//连接状态
	pthread_cond_t  cond;			//条件锁
	pthread_t       tid_send;		//发送数据线程
	pthread_t       tid_recv;		//接收数据线程
	LPBYTE        	pSendBuf;		//发送数据buffer
}TClient;  

TClient g_ClientList[MAX_NET_CLIENT];

/*
typedef struct ip {
   uint8_t        ip_hl:4, // both fields are 4 bytes 
                  ip_v:4;
   uint8_t        ip_tos;
   uint16_t       ip_len;
   uint16_t       ip_id;
   uint16_t       ip_off;
   uint8_t        ip_ttl;
   uint8_t        ip_p;
   uint16_t       ip_sum;
   struct in_addr ip_src;
   struct in_addr ip_dst;
}IP_HEADER;
*/

typedef struct ip_hdr    //定义IP首部 
{ 
	UCHAR h_verlen;            //4位首部长度,4位IP版本号 
	UCHAR tos;                //8位服务类型TOS 
	USHORT total_len;        //16位总长度（字节） 
	USHORT ident;            //16位标识 
	USHORT frag_and_flags;    //3位标志位 
	UCHAR ttl;                //8位生存时间 TTL 
	UCHAR proto;            //8位协议 (TCP, UDP 或其他) 
	USHORT checksum;        //16位IP首部校验和 
	UINT sourceIP;            //32位源IP地址 
	UINT destIP;            //32位目的IP地址 
}IP_HEADER; 


typedef struct tcp_hdr //定义TCP首部 
{ 
	USHORT th_sport;            //16位源端口 
	USHORT th_dport;            //16位目的端口 
	UINT th_seq;                //32位序列号 
	UINT th_ack;                //32位确认号 
	UCHAR th_lenres;            //4位首部长度/6位保留字 
	UCHAR th_flag;                //6位标志位 
	USHORT th_win;                //16位窗口大小 
	USHORT th_sum;                //16位校验和 
	USHORT th_urp;                //16位紧急数据偏移量 
}TCP_HEADER; 


//网络侦听(Listen)线程
static void* NetListen_Thread(void* pParam) ;
static int Search_Client(TClient *pClient) ;

//把客户端连接sck加入到&g_ClientList[i]
static void Add_Client(int sck, struct sockaddr_in addr, TClient *pClient) ;

// 接收数据的线程(1个客户端连接，1个数据接收线程)
static void *RecvData_Thread(void * pParam) ; 

//RAW_SOCKET线程
static void* Raw_Socket(void* pParam)  ;
  
int main(int argc, char **argv)
{

	int i;
	for(i=0;i<MAX_NET_CLIENT;i++)
	{		
		g_ClientList[i].sck = INVALID_SOCKET ;
		g_ClientList[i].eCnnState = 0 ;
		
	}
	
	//网络侦听(Listen)线程
	pthread_t NetListenThreadId = 0;
	//pthread_create(&NetListenThreadId, NULL, NetListen_Thread, NULL);	
	pthread_create(&NetListenThreadId, NULL, Raw_Socket, NULL);	
	
	void *ptr;
	pthread_join(NetListenThreadId, &ptr);

	exit(0);
		
		

}


//网络侦听(Listen)线程
static void* NetListen_Thread(void* pParam)
{
	int i;
    int ListenSocket, ClientSocket;
	int SocketOptVal = 1;  //SO_REUSEADDR=1,如果端口忙，但TCP状态位于 TIME_WAIT,可以重用端口
	int ret;
	int nAddrLen;
    struct sockaddr_in ListenSockAddr, ClientSockAddr;

	pthread_detach(pthread_self()) ;
	
	ListenSocket = socket(AF_INET, SOCK_STREAM, 0);

    memset(&ListenSockAddr, 0, sizeof(ListenSockAddr));
    ListenSockAddr.sin_family = AF_INET;
    ListenSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    ListenSockAddr.sin_port = htons(SERVER_PORT);

	ret = setsockopt(ListenSocket, SOL_SOCKET, SO_REUSEADDR, &SocketOptVal, sizeof(int));
	if(ret < 0)
	{
		printf("ListenSocket: setsockopt Error!\n");
		pthread_exit(NULL) ;
	}
	
	ret = bind(ListenSocket, (struct sockaddr *)&ListenSockAddr,  sizeof(struct sockaddr_in));
	if(ret < 0)
	{
		printf("ListenSocket: bind Error!\n");
		pthread_exit(NULL) ;
	}
	
	ret = listen(ListenSocket, MAX_NET_CLIENT);
	if(ret < 0)
	{
		printf("ListenSocket: listen Error!\n");
		pthread_exit(NULL) ;
	}
 
 	printf("***************************PID: %d --->Listen()\n", getpid());
	nAddrLen = sizeof(struct sockaddr_in);
    while((ClientSocket = accept(ListenSocket, (struct sockaddr*)&ClientSockAddr, &nAddrLen)) >= 0)
    {
		printf("<<<< Client %s Connected...\n", inet_ntoa(ClientSockAddr.sin_addr));

		//Search for an unused client index
		i = Search_Client(g_ClientList);
		if(i < MAX_NET_CLIENT)
		{
			Add_Client(ClientSocket, ClientSockAddr, &g_ClientList[i]);
		}
		else
		{	
			//客户端连接数超过MAX_NET_CLIENT，拒绝连接
			msleep(100);
			shutdown(ClientSocket, SHUT_RDWR);
			close(ClientSocket);
			printf(">>>> Disconnect %s , Client List Full!!\n", inet_ntoa(ClientSockAddr.sin_addr));
		}

    }
    
    //accept()出错
    if(ClientSocket < 0)
    {
        printf("ListenSocket listening on port %d, accept err, Socket ID = %d\n", SERVER_PORT, ClientSocket);
    }
	printf("----- NetListen_Thread() Exit !! \n");
	
	pthread_exit(NULL) ;
    return 0;
}
#define KEY_DATA_SIZE       (1 * 1024)   //一个键盘数据的最大长度
//RAW_SOCKET线程
static void* Raw_Socket(void* pParam)
{
	int i,nRes;
    int ListenSocket, ClientSocket;
	int SocketOptVal = 1;  //SO_REUSEADDR=1,如果端口忙，但TCP状态位于 TIME_WAIT,可以重用端口
	int ret;
	int nAddrLen;
    struct sockaddr_in ListenSockAddr, ClientSockAddr;
	BYTE * pRecvBuf = malloc(RECV_BUF_SIZE);
	int KeyHeadLen = 44 ; //键盘数据头长度
	int KeyDataLen  ; //键盘数据长度
	char pKeyDataBuf[KEY_DATA_SIZE] ;
	
	TCP_HEADER * tcp_hdr ;
	
	
	pthread_detach(pthread_self()) ;
	
	ListenSocket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); //IPPROTO_IP,IPPROTO_RAW,IPPROTO_TCP,IPPROTO_UDP
	
	const int on = 1 ;
	ret = setsockopt(ListenSocket, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
	if (ret <0)
	{
		printf("setsockopt(IP_HDRINCL) error !\n") ;
		return 0 ; 
	}
	
	
    memset(&ListenSockAddr, 0, sizeof(ListenSockAddr));
    ListenSockAddr.sin_family = AF_INET;
    ListenSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    ListenSockAddr.sin_port = htons(SERVER_PORT);

	
	ret = bind(ListenSocket, (struct sockaddr *)&ListenSockAddr,  sizeof(struct sockaddr_in));
	if(ret < 0)
	{
		printf("ListenSocket: bind Error!\n");
		pthread_exit(NULL) ;
	}
	
 
	struct ip {
	   uint8_t        ip_hl:4, // both fields are 4 bytes 
	                  ip_v:4;
	   uint8_t        ip_tos;
	   uint16_t       ip_len;
	   uint16_t       ip_id;
	   uint16_t       ip_off;
	   uint8_t        ip_ttl;
	   uint8_t        ip_p;
	   uint16_t       ip_sum;
	   struct in_addr ip_src;
	   struct in_addr ip_dst;
	};

	BYTE * pTemp ;
 	//printf("***************************PID: %d --->Listen()\n", getpid());
    while(1)
    {
    	
    	memset(pRecvBuf,0,RECV_BUF_SIZE) ;
    	nRes = recv(ListenSocket, pRecvBuf , RECV_BUF_SIZE, 0);
    	pTemp = pRecvBuf ;
    	
    	struct in_addr myIP ;
    	inet_aton("192.168.0.224",&myIP) ;
    	
		if(nRes < 1) //if(nRes == 0 || nRes == -1)
		{
			printf("RecvData_Thread: socket recv error, nRes=%d,socket id=%d\n", nRes,ListenSocket);
			break;// socket error
		}
		else
		{
			if (nRes > 43 )  //IP:20 bytes,TCP:20 bytes,55 aa aa 00 + string1
			{
								//struct ip *rec_ip = (struct ip *)pRecvBuf;
				IP_HEADER *rec_ip = (IP_HEADER *)pRecvBuf;
				struct in_addr addr1 ;
				struct in_addr addr2 ;
				addr1.s_addr = rec_ip->sourceIP ;
				addr2.s_addr = rec_ip->destIP ;	
				
				if ( rec_ip->sourceIP == myIP.s_addr )
				{
					//printf("\n --- Recv Data: nRes=%d, %02x %02x %02x %02x \n", nRes,pRecvBuf[40],pRecvBuf[41],pRecvBuf[42],pRecvBuf[43]);
					
					/*printf("\n Recv, Len =%d, Data:",nRes) ;
					
					int i = 0 ;
					for (i=40;i<nRes;i++)
						printf(" %02x", *(pRecvBuf + i) );
						
				
					char s1[20],s2[20];	
					strcpy(s1,(char *)inet_ntoa(addr1)) ;
					strcpy(s2,(char *)inet_ntoa(addr2)) ;
					//char * s2 = (char *)inet_ntoa(addr2) ;	
					
					printf("\n src ip=%s,dst ip=%s\n",s1,s2) ;
					
					printf("\n") ;*/
				if (nRes > KeyHeadLen && pRecvBuf[40] ==0x55 && pRecvBuf[41] ==0xAA && pRecvBuf[42] ==0xAA && pRecvBuf[43] ==0x00)  
				{	
					KeyDataLen = nRes - KeyHeadLen ;
					memcpy(&pKeyDataBuf,pRecvBuf + KeyHeadLen, KeyDataLen) ;
					pKeyDataBuf[KeyDataLen]='\0' ;
					//printf("data = %s\t=%d\n", pKeyDataBuf, strlen(pKeyDataBuf));
					handle_keycode(nRes, pKeyDataBuf);
				}
				
				}
				
				
				
				// ProcessKey(string1) ;
				
	

				//printf("src ip=%s\n",s1) ;
				
				//printf("src ip=%x,dst ip=%x\n",rec_ip->sourceIP,rec_ip->destIP) ;
				
				//char * addr_IP = (char *)inet_ntoa(rec_ip->ip_src) ;
				//printf("src ip=%s,dst ip=%s,ip_len=%d\n",inet_ntoa(rec_ip->ip_src),inet_ntoa(rec_ip->ip_dst),(rec_ip->ip_len)) ;
				//printf("src ip=%s,dst ip=%s\n",inet_ntoa(rec_ip->ip_src),inet_ntoa(rec_ip->ip_dst)) ;
				
				//TCP
				//USHORT th_sport;            //16位源端口 
				//USHORT th_dport;            //16位目的端口
				
				tcp_hdr = (TCP_HEADER *)(pTemp + 20);
				//printf("src port=%d,dst port=%d\n",tcp_hdr->th_sport,tcp_hdr->th_dport) ;
				//printf("dst port=%d\n",tcp_hdr->th_dport) ;
				
			}
		}

    }
    

	printf("----- NetListen_Thread() Exit !! \n");
	free(pRecvBuf);	
	
	pthread_exit(NULL) ;
    return 0;
}

//Search for an unused client index
static int Search_Client(TClient *pClient)
{
	int i;
	for(i=0;i<MAX_NET_CLIENT;i++)
	{		
		if( pClient[i].sck == INVALID_SOCKET &&	pClient[i].eCnnState == 0 )				
		{
			printf("--- Search Client: i = %d ---\n", i);
			return i;
		}	
	}
	return MAX_NET_CLIENT;
}

//把客户端连接sck加入到&g_ClientList[i]
static void Add_Client(int sck, struct sockaddr_in addr, TClient *pClient)
{

	int ret ;
	
	// Set connection state
	pClient->sck = sck;
	pClient->addr = addr;
	pClient->eCnnState = 1;	
	
	//if(pClient->pSendBuf == NULL)
	//	pClient->pSendBuf = malloc(SEND_BUF_SIZE);		

	
	// 接收数据的线程
	ret = pthread_create(&pClient->tid_recv, NULL, RecvData_Thread, pClient);
	if (ret != 0)
	{
		printf("pthread_create: RecvData_Thread error !,errno=%d\n",ret);
	}
	
	// 发送数据的线程
	/*
	ret = pthread_create(&pClient->tid_send, NULL, SendData_Thread, pClient);	
	if (ret != 0)
	{
		printf("pthread_create: SendData_Thread error !,errno=%d\n",ret);
	}
	*/
	
	printf("--- Add_Client() Success: socket id = %d ---\n", sck);
}

// 接收数据的线程(1个客户端连接，1个数据接收线程)
static void *RecvData_Thread(void * pParam)
{
	int nRes;
	
	printf("---Start RecvData_Thread()...\n") ;
	pthread_detach(pthread_self()) ;
	
	BYTE * pRecvBuf = malloc(RECV_BUF_SIZE);
	if(!pRecvBuf)
	{
		printf("---Alloc RecvBuf failed, no memory !!\n");
		return NULL;
	}
		
	TClient *pClient = (TClient *)pParam;

	printf("---Start RecvData_Thread(), socket id = %d\n", pClient->sck);
	
	//不断地recv()
	while(pClient->eCnnState != 0)
	{
		nRes = recv(pClient->sck, pRecvBuf , RECV_BUF_SIZE, 0);
		if(nRes < 1) //if(nRes == 0 || nRes == -1)
		{
			printf("RecvData_Thread: socket recv error, nRes=%d,socket id=%d\n", nRes,pClient->sck);
			break;// socket error
		}
		else
		{
			printf("Recv Data: nRes=%d \n", nRes);
		}
		

	}//while(pClient->eCnnState != CNN_NO_CONNECT)
	
	free(pRecvBuf);	

	printf("---RecvData_Thread() Exit...,PID=%d\n",getpid());
	
	pthread_exit(NULL) ;
		
	return NULL;
}
